package com.hongdee.crm.task.service.impl;

import com.hongdee.annotation.MethodComment;
import com.hongdee.common.util.DateUtils;
import com.hongdee.common.util.StringUtil;
import com.hongdee.crm.task.dao.IBcMaintainTypeTaskDao;
import com.hongdee.crm.task.dao.ITCrmCarMaintainTaskDao;
import com.hongdee.crm.task.dao.ITCrmTaskDao;
import com.hongdee.crm.task.dto.MainTainDTO;
import com.hongdee.crm.task.entity.TCrmTask;
import com.hongdee.crm.task.service.ITCrmCarMaintainTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 名  称: TCrmCarDbMaintainTaskServiceImpl
 * 类  型: class
 * 描  述: 定保任务类
 * 路  径: com.hongdee.crm.task.service.impl
 * 作  者: wangshuai
 * 日  期:2017/2/28 10:23
 */
@Component("dbCarMaintainTaskService")
public class TCrmCarDbMaintainTaskServiceImpl implements ITCrmCarMaintainTaskService {

    @Autowired
    private ITCrmCarMaintainTaskDao carMaintainTaskDao;
    @Autowired
    private ITCrmTaskDao taskDao;

    @Autowired
    private IBcMaintainTypeTaskDao bcMaintainTypeTaskDao;

    private final String BY_CODE="by";
    private final String YYYYMMDD="yyyy-MM-dd";
    private final int LIMIT = 1000;


    private final String DB="db";
    private final String MBY="mby";
    private final String TXTS="txts";
    private final String JSYF="jsyf";
    private final String MBR="mbr";

    private MainTainDTO mbyMainTainDTO;
    private MainTainDTO mbrMainTainDTO;

    /**
     * 车辆定保任务
     * sql查询规则：
     * 1、根据车辆保养信息表，查询除首保以外的保养信息
     * 2、按时间排序，查询出当前时间向前推六个月以内的，每辆车最后一条保养信息；
     * 计算步骤：
     * 1、查询出定保存配置公司信息
     * 2、遍历公司信息，查询车辆保养表，查询符合条件的车辆信息
     * 3、遍历车辆信息，生成TCrmTask任务实体类
     *  1）、取出车辆下一次保养时间、上一次保养时间
     *  2）、判断下一次保养时间是否大于当前时间，如果大于当前时间，则执行下次保养时间；如果小于当前时间，则执行+6个月后的时间；
     *  3）、判断下一次保养时间是否在下月1号至下下月1号零点之间，如在则执行查看任务是否已经存在，此处定保查询需要配合执行日期；
     *  4）、判断任务是否已经存在，如不存在，则生成TCrmTask实体类保存，如已存在则跳出本次循环
     * @throws Exception
     */
//    @Scheduled(cron="0 30 2 28 * ?") //每月28日2点30执行
    @Override
    @MethodComment(name = "定保 定保月定时任务")
    public Integer carMaintainQuartz() throws Exception {
        Integer nums=0;
        List<Map<String,Object>> companyList=carMaintainTaskDao.findCompanyList(DB+"_"+MBY,DB+"_"+MBR);
        //遍历公司信息
        for(Map<String,Object> map:companyList){
            //取得公司ID
            String companyId=String.valueOf(map.get("company_id"));
            int num=this.carMaintain(companyId,"","");
            nums+=num;
        }
        return nums;
    }

    @Override
    public Integer carMaintain(String companyId,String startTime,String endTime) throws Exception {
        long nowTime=MaintainUtil.getNowTime();
        long beforeSixTime= DateUtils.addMonthLongTime(nowTime,-6);
        //根据公司ID 判断是否有定保任务 定保月任务
        List<Map<String,Object>> paramList=bcMaintainTypeTaskDao.findSetMaintainType(companyId,DB);
        Integer nums=0;
        if(paramList!=null) {
            this.getMainTainParamInfo(paramList,companyId);
            nums+=findCarDbMaintain(companyId,nowTime,beforeSixTime,startTime,endTime,mbrMainTainDTO.getCode());
            nums+=findCarDbMaintain(companyId,nowTime,beforeSixTime,startTime,endTime,mbyMainTainDTO.getCode());
        }
        return nums;
    }

    /**
     * 根据公司ID 查询车辆信息
     * @param compnayId
     * @param nowTime
     * @throws Exception
     */
    private Integer findCarDbMaintain(String compnayId,long nowTime,long beforeSixTime,String startTime,String endTime,String code) throws Exception {
        Integer nums=0;
        int start=0;
        while(true){
            List<Map<String,Object>> lists=carMaintainTaskDao.carDbMaintainList(compnayId,beforeSixTime,start*LIMIT,LIMIT,DB,code);
            if(lists==null){
                start=0;
                break;
            }else{
                List<TCrmTask> crmTasks=this.analyCars(lists,compnayId,nowTime,startTime,endTime,code);
                if(crmTasks.size()>0){
//                    taskDao.saveOrUpdateList(crmTasks);
                    nums+=crmTasks.size();
                    long start1 = System.currentTimeMillis();
                    carMaintainTaskDao.insertMaintailLists(crmTasks);
                    long end = System.currentTimeMillis();
                    System.out.println("运行时间：" + (end - start1) + "毫秒");//应该是end - start
                }
            }
            start++;
        }
        return nums;
    }

    /**
     * 解析车辆信息,根据车辆信息 生成相应任务类
     * @param lists
     * @param companyId
     * @param nowTime
     * @return
     * @throws Exception
     */
    private List<TCrmTask> analyCars(List<Map<String,Object>> lists,String companyId,long nowTime,String startTime,String endTime,String code) throws Exception {
        List<TCrmTask> crmTasks=new ArrayList<>();
        for (Map<String,Object> map:lists) {
            String plateNum="";
            if(map.get("plate_num")==null){
                String vin=String.valueOf(map.get("vin"));
                plateNum=vin.substring(vin.length()-6,vin.length());
                map.put("plate_num",plateNum);
            }
            if(map.get("next_maintain_time")==null){
                continue;
            }
            //1、取出下一次保养时间 与当前时间相比
            long nextMaintainTime=Long.valueOf(String.valueOf(map.get("next_maintain_time")));
            //2、取出本次保养时间
            long maintainTime=Long.valueOf(String.valueOf(map.get("maintain_time")));
            long sixMonthTime=DateUtils.addMonthLongTime(maintainTime,+mbyMainTainDTO.getJsyfNums().intValue());
            //计算时间，返回结果sbflag true首保日 false 月，tasktime任务提醒时间 byTime理论上保养最后时间点
            switch (code){
                case "db_mbr":
                    this.saveDbTaskMbr(nextMaintainTime,sixMonthTime,nowTime,startTime,endTime,companyId,crmTasks,maintainTime,map);
                    break;
                case "db_mby":
                    this.saveDbTaskMby(nextMaintainTime,sixMonthTime,nowTime,startTime,endTime,companyId,crmTasks,maintainTime,map);
                    break;
            }



//            List<Map<String,Object>> taskMapList = this.dbMaintainTime(maintainTime,nextMaintainTime, nowTime,carId);
//            for (Map<String,Object> taskMap:taskMapList) {
//                long taskTime=Long.parseLong(String.valueOf(taskMap.get("taskTime")));
//                long byTime=Long.parseLong(String.valueOf(taskMap.get("byTime")));
//                boolean sbflag=Boolean.parseBoolean(String.valueOf(taskMap.get("db")));
//                //判断日期是否在下月之中也就是下月1号至下下月1号，如当前月3月，那么日期需要在4.1至5.1之间
//                boolean flag = DateUtils.checkTime(byTime,nowTime);
//                if(!"".equals(startTime) && !"".equals(endTime)){
//                    flag=DateUtils.checkTime(byTime,startTime,endTime);
//                }
//                if (flag) {
//
//                    //保存任务之前需要判断
//                    if(sbflag){
//                        //定保日任务
//                        //根据车辆 查看首保日任务是否存在 定保需要加上时间查询
//                        boolean taskFlag=this.checkSbTask(companyId,carId,mbrMainTainDTO.getCode(),byTime);
//                        if(taskFlag){//已经存在，则直接跳出循环
////                            System.out.println("首保日任务已经存在");
//                            continue;
//                        }
//                    }else{
//                        //定保月任务 无需查询是否存在定保日任务 定保需要加上时间查询
//                        boolean taskFlag=this.checkSbTask(companyId,carId,mbyMainTainDTO.getCode(),byTime);
//                        if(taskFlag){//已经存在，则直接跳出循环
////                            System.out.println("首保月任务已经存在");
//                            continue;
//                        }
//                    }
//                    //2、如果存在首保存日任务 则创建首保月任务
//                    TCrmTask task = this.saveTask(map, taskTime, byTime, sbflag, maintainTime);
//                    crmTasks.add(task);
//                }
//            }

        }
        return crmTasks;
    }

    private void saveDbTaskMbr(Long nextMaintainTime,Long sixMonthTime,Long nowTime,String startTime,String endTime,
                               String companyId,List<TCrmTask> crmTasks,Long maintainTime,Map<String,Object> map) throws Exception {
        if(nextMaintainTime<sixMonthTime) {
            long taskTime=nextMaintainTime;
            if(mbrMainTainDTO.getJsyfNums()!=null) {
                long byTime = DateUtils.addDayLongTime(nextMaintainTime, -mbrMainTainDTO.getTxtsNums().intValue());

                String carId = String.valueOf(map.get("car_id"));

                boolean flag = DateUtils.checkTime(byTime, nowTime);
                if (!"".equals(startTime) && !"".equals(endTime)) {
                    flag = DateUtils.checkTime(byTime, startTime, endTime);
                }
                if (flag) {
                    boolean taskFlag = taskDao.checkTaskByVinAndId(companyId,StringUtil.formatEmpty(map.get("vin")), carId,
                            mbrMainTainDTO.getCode(),BY_CODE, DateUtils.formatLongTimeByYYYYMMDD(byTime));
                    if (!taskFlag) {//已经存在，则直接跳出循环
                        String tpl = "%s的车，车主[%s],%s为常保，上次保养时间%s.";
                        TCrmTask task = this.saveTask(map, taskTime, byTime, tpl, maintainTime, mbrMainTainDTO.getCode());
                        crmTasks.add(task);
                    }
                }
            }
        }
    }

    private void saveDbTaskMby(Long nextMaintainTime,Long sixMonthTime,Long nowTime,String startTime,String endTime,
                               String companyId,List<TCrmTask> crmTasks,Long maintainTime,Map<String,Object> map) throws Exception {
        if(nextMaintainTime>=sixMonthTime) {
            this.saveDbTaskMbybyTime(nextMaintainTime,sixMonthTime,nowTime,startTime,endTime,companyId,crmTasks,maintainTime,map);
        }
        if(nextMaintainTime<nowTime){
            this.saveDbTaskMbybyTime(nextMaintainTime,sixMonthTime,nowTime,startTime,endTime,companyId,crmTasks,maintainTime,map);
        }
        if(nextMaintainTime>nowTime && nextMaintainTime<sixMonthTime){
            this.saveDbTaskMbybyTime(nextMaintainTime,sixMonthTime,nowTime,startTime,endTime,companyId,crmTasks,maintainTime,map);
        }
    }

    private void saveDbTaskMbybyTime(Long nextMaintainTime,Long sixMonthTime,Long nowTime,String startTime,String endTime,
                                     String companyId,List<TCrmTask> crmTasks,Long maintainTime,Map<String,Object> map) throws Exception {
        long taskTime = sixMonthTime;
        if(mbyMainTainDTO.getJsyfNums()!=null) {
            long byTime = DateUtils.addDayLongTime(sixMonthTime, -mbyMainTainDTO.getTxtsNums().intValue());

            String carId = String.valueOf(map.get("car_id"));
            String vin=String.valueOf(map.get("vin"));
            //判断日期是否在下月之中也就是下月1号至下下月1号，如当前月3月，那么日期需要在4.1至5.1之间
            boolean flag = DateUtils.checkTime(byTime, nowTime);
            if (!"".equals(startTime) && !"".equals(endTime)) {
                flag = DateUtils.checkTime(byTime, startTime, endTime);
            }
            if (flag) {
                boolean taskFlag = taskDao.checkTaskByVinAndId(companyId,StringUtil.formatEmpty(map.get("vin")), carId,
                        mbrMainTainDTO.getCode(),BY_CODE, DateUtils.formatLongTimeByYYYYMMDD(byTime));
                if (!taskFlag) {//已经存在，则直接跳出循环
                    String tpl = "%s的车，车主[%s],%s为常保，上次保养时间%s.[目标月]";
                    TCrmTask task = this.saveTask(map, taskTime, byTime, tpl, maintainTime, mbyMainTainDTO.getCode());
                    crmTasks.add(task);
                }
            }
        }
    }


    /**
     * 保存首保类任务
     * @param mTmp
     * @param taskTime
     * @throws Exception
     */
    private TCrmTask saveTask(Map<String,Object> mTmp,long taskTime,long byTime,String tpl,long maintainTime,String code) throws Exception {
        TCrmTask task = new TCrmTask();
        task.setCreateTime(new Date().getTime());
        task.setVIN(mTmp.get("vin").toString());
        task.setCarId(mTmp.get("car_id").toString());
        task.setPlateNum(mTmp.get("plate_num").toString());
        task.setCompanyId(mTmp.get("company_id").toString());
        task.setLinkman(StringUtil.formatNull(mTmp.get("contact_name")));
        if(mTmp.get("contact_phone")!=null) {
            task.setLinkphone(mTmp.get("contact_phone").toString());
        }
//        task.setSaId(mTmp.get("said")+"");
        task.setExpectDate(DateUtils.formatLongTime(byTime,YYYYMMDD));
        task.setStatus("0");
        task.setIsBack("0");
        task.setTypePCode(BY_CODE);
        String contentStr="";
        String byTimeStr=DateUtils.formatLongTime(byTime,YYYYMMDD);
        String taskTimeStr=DateUtils.formatLongTime(taskTime,YYYYMMDD);
        String maintainTimeStr=DateUtils.formatLongTime(maintainTime,YYYYMMDD);
        task.setTypeCode(code);
        contentStr=String.format(tpl,task.getPlateNum(),task.getLinkman(),taskTimeStr,maintainTimeStr);
//
//            contentStr.append(task.getPlateNum()+"的车，车主["+task.getLinkman()+"],"+taskTimeStr+"为常保，上次保养时间"+maintainTimeStr+".");
////            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]下次保养提醒时间为："+taskTimeStr+",建议最晚下次保养时间为："+byTimeStr+";联系方式:"+task.getLinkphone());
//            contentStr.append(task.getPlateNum()+"的车，车主["+task.getLinkman()+"],"+taskTimeStr+"为常保，上次保养时间"+maintainTimeStr+".[目标月]");
////            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]下次保养提醒时间为："+taskTimeStr+",建议最晚下次保养时间为："+byTimeStr+";联系方式:"+task.getLinkphone());


        task.setContent(contentStr);
        return task;
    }


    /**
     * 计算定保时间
     * @param maintainTime 上一次保养时间
     * @param nextMaintainTime 根据保养里程 计算的下一次保养时间
     * @param nowTime 当前时间
     * @return
     * @throws Exception
     */
    private List<Map<String,Object>> dbMaintainTime(long maintainTime,long nextMaintainTime,long nowTime,String id) throws Exception {
        List<Map<String,Object>> list=new ArrayList<>();
        long sixMonthTime=DateUtils.addMonthLongTime(maintainTime,+mbyMainTainDTO.getJsyfNums().intValue());
        if(nextMaintainTime>=sixMonthTime) {
            Map<String,Object> mbyMap=new HashMap<>();
            mbyMap.put("db", false);
            mbyMap.put("byTime", DateUtils.addDayLongTime(sixMonthTime, -mbyMainTainDTO.getTxtsNums().intValue()));
            mbyMap.put("taskTime", sixMonthTime);
            list.add(mbyMap);
        }else {
//            if(nextMaintainTime>=nowTime){
            Map<String, Object> mbrMap = new HashMap<>();
            mbrMap.put("db", true);
            mbrMap.put("byTime", DateUtils.addDayLongTime(nextMaintainTime, -mbrMainTainDTO.getTxtsNums().intValue()));
            mbrMap.put("taskTime", nextMaintainTime);
            list.add(mbrMap);
//            }else {
            Map<String,Object> mbyMap=new HashMap<>();
            mbyMap.put("db", false);
            mbyMap.put("byTime", DateUtils.addDayLongTime(sixMonthTime, -mbyMainTainDTO.getTxtsNums().intValue()));
            mbyMap.put("taskTime", sixMonthTime);
            list.add(mbyMap);
//            }
        }


//        Map<String,Object> taskMap=new HashMap<>();
//        boolean db=false;
//        Long taskTime=null;
//        taskMap.put("byTime",nextMaintainTime);
//        //下一次保养时间 与当前时间进行比较 如果小于当前时间,说明
//        if(nowTime>nextMaintainTime){
//
//            db=false;
//            //定保月
//            long sixMonthTime=DateUtils.addMonthLongTime(maintainTime,+mbyMainTainDTO.getJsyfNums().intValue());
//            //生成首保月时间点
//            taskTime=DateUtils.addDayLongTime(sixMonthTime,-mbyMainTainDTO.getTxtsNums().intValue());
//            taskMap.put("byTime",sixMonthTime);
//        }else{
//            db=true;
//            //定保日
//            //生成首保日时间点
//            taskTime=DateUtils.addDayLongTime(nextMaintainTime,-mbrMainTainDTO.getTxtsNums().intValue());
//        }
//        taskMap.put("db",db);
//        taskMap.put("taskTime",taskTime);
//        return taskMap;
        return list;
    }

    /**
     * 检测任务是否已经存在，如果已经存在返回true，未存在返回false
     * @param companyId
     * @param carId
     * @param code
     * @return
     * @throws Exception
     */
    private boolean checkSbTask(String companyId,String carId,String code,long expectDate) throws Exception {
        String expectDateStr=DateUtils.formatLongTime(expectDate,YYYYMMDD);
        List<Map<String,Object>> lists=taskDao.findTasksByVin(companyId,carId,BY_CODE,code,expectDateStr);
        if(lists!=null){
            if(lists.size()>0){
                return true;
            }
        }
        return false;
    }

    /**
     * 保存首保类任务
     * @param mTmp
     * @param taskTime
     * @throws Exception
     */
    private TCrmTask saveTask(Map<String,Object> mTmp,long taskTime,long byTime,boolean sbflag,long maintainTime) throws Exception {
        TCrmTask task = new TCrmTask();
        task.setVIN(mTmp.get("vin").toString());
        task.setCarId(mTmp.get("car_id").toString());
        task.setPlateNum(mTmp.get("plate_num").toString());
        task.setCompanyId(mTmp.get("company_id").toString());
        task.setLinkman(mTmp.get("contact_name").toString());
        if(mTmp.get("contact_phone")!=null) {
            task.setLinkphone(mTmp.get("contact_phone").toString());
        }
//        task.setSaId(mTmp.get("said")+"");
        task.setExpectDate(DateUtils.formatLongTime(byTime,YYYYMMDD));
        task.setStatus("0");
        task.setTypePCode(BY_CODE);
        StringBuffer contentStr=new StringBuffer();
        String byTimeStr=DateUtils.formatLongTime(byTime,YYYYMMDD);
        String taskTimeStr=DateUtils.formatLongTime(taskTime,YYYYMMDD);
        String maintainTimeStr=DateUtils.formatLongTime(maintainTime,YYYYMMDD);
        if(sbflag){
            //定保日
            task.setTypeCode(mbrMainTainDTO.getCode());
            contentStr.append(task.getPlateNum()+"的车，车主["+task.getLinkman()+"],"+taskTimeStr+"为常保，上次保养时间"+maintainTimeStr+".");
//            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]下次保养提醒时间为："+taskTimeStr+",建议最晚下次保养时间为："+byTimeStr+";联系方式:"+task.getLinkphone());
        }else{
            //定保月
            task.setTypeCode(mbyMainTainDTO.getCode());
            contentStr.append(task.getPlateNum()+"的车，车主["+task.getLinkman()+"],"+taskTimeStr+"为常保，上次保养时间"+maintainTimeStr+".[目标月]");
//            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]下次保养提醒时间为："+taskTimeStr+",建议最晚下次保养时间为："+byTimeStr+";联系方式:"+task.getLinkphone());
        }


        task.setContent(contentStr.toString());
        return task;
    }


    /**
     * 解析参数信息 生成相应的DTO类
     * @param params
     * @param companyId
     * @throws Exception
     */
    private void getMainTainParamInfo(List<Map<String,Object>> params,String companyId)throws Exception{
        //遍历
//        for (Map<String,Object> map:params) {
//            String mapCode=String.valueOf(map.get("code"));
//            if((DB+"_"+MBY).equals(mapCode)){
        //根据code值 查询其下属信息
        List<Map<String,Object>> mbyList=carMaintainTaskDao.findCompanyParamList(companyId,DB+"_"+MBY);
        if(mbyList!=null) {
            mbyMainTainDTO = MainTainDTO.analyParams(mbyList, DB + "_" + MBY + "_" + TXTS, DB + "_" + MBY + "_" + JSYF, DB + "_" + MBY);
            mbyMainTainDTO.setCode(DB + "_" + MBY);
            this.setMbyMainTainDTO(mbyMainTainDTO);
        }
//            }else if((DB+"_"+MBR).equals(mapCode)){
        List<Map<String,Object>> mbrList=carMaintainTaskDao.findCompanyParamList(companyId,DB+"_"+MBR);
        if(mbrList!=null) {
            mbrMainTainDTO = MainTainDTO.analyParams(mbrList, DB + "_" + MBR + "_" + TXTS, DB + "_" + MBR + "_" + JSYF, DB + "_" + MBR);
            mbrMainTainDTO.setCode(DB + "_" + MBR);
            this.setMbrMainTainDTO(mbrMainTainDTO);
        }
//            }
//        }
    }


    public MainTainDTO getMbyMainTainDTO() {
        return mbyMainTainDTO;
    }

    public void setMbyMainTainDTO(MainTainDTO mbyMainTainDTO) {
        this.mbyMainTainDTO = mbyMainTainDTO;
    }

    public MainTainDTO getMbrMainTainDTO() {
        return mbrMainTainDTO;
    }

    public void setMbrMainTainDTO(MainTainDTO mbrMainTainDTO) {
        this.mbrMainTainDTO = mbrMainTainDTO;
    }
}
